#include <stdio.h>
#include <assert.h>

#define CUBE_COUNT 3
typedef struct llist{
	struct llist* next;
	int val;
}list;

list* head;

typedef enum direction{
	fright=0,
	sright,
	fleft,
	sleft
}direct;


//-3 -2 -1 1 2 3 -->1 2 3  5 6 7
int getcubeval(int* cube){
	int i=0;
	int sum=0;
	for(i=0;i<CUBE_COUNT;i++){
		sum=cube[i]+4+sum*10;
	}
	return sum;
}


void print(int* cube){
	int i;
	for(i=0;i<CUBE_COUNT;i++){
		printf("%2d,",cube[i]);
	}
	printf(", sum=%d\n",getcubeval(cube));
}

void godirect(int* cube,int dir){
	assert(dir>=0 && dir<4);
	int temp;
	switch(dir){
		case 0://go through
		case 1://go right a b -> -b a
			temp=cube[dir];
			cube[dir]=-1*cube[dir+1];
			cube[dir+1]=temp;
			break;
		case 2://go through
		case 3://go left a b ->b -a
			dir=dir-2;
			temp=cube[dir];
			cube[dir]=cube[dir+1];
			cube[dir+1]=-1*temp;
			break;
	}
}

//1,2,3  goright(,0) -> -2 ,1,3  gorith(,1) -->1,-3,2

list* lastpos=0;

void add2list(int* cube){
	//compute cube to number
	int sum=getcubeval(cube);
	//printf("add %d ,%x,%x\n",sum,head,lastpos);
	if(lastpos==0){
		printf("set lastpos to head\n");
		lastpos=head;
	}else{
		list* nn=(list*)malloc(sizeof(list));
		lastpos->next=nn;
		lastpos=nn;
	}
	lastpos->val=sum;
}

int nocube(int* cube){
	list* p=head;
	for(;p!=NULL;p=p->next){
		int sum=getcubeval(cube);
		if(p->val==sum){
			return 0;
		}
	}
	return 1;
}
int ccount=0;
int cc=0;

void showCube(int* cube){
	ccount++;
	if(ccount>100)
		return;
		
	int dir=0;
	for(;dir<4;dir++){
		//printf("go direct %d\n",dir);
		godirect(cube,dir);	
		int n=nocube(cube);	
		if(n==1){
			cc++;
			add2list(cube);
			print(cube);
			//copy cube
			int* ncube=(int*)malloc(sizeof(int)*CUBE_COUNT);
			int i;
			for(i=0;i<CUBE_COUNT;i++)ncube[i]=cube[i];
			showCube(ncube);
		}
	}
	
}

void printlist(){
	list* h=head;
	for(;h!=NULL;h=h->next){
		printf("%d,",h->val);
	}
}

int listlen(){
	list* h=head;
	int i=0;
	for(;h!=NULL;h=h->next){
		i++;
	}
	return i;
}

int cmp(const void* la,const void *lb){
	//printf("%x,%x\n",la,lb);
	list** lla=(list**)la;
	//list** llb=lla+sizeof(list*);
	list** llb=(list**)lb;
	if(llb>0){
		//printf("compare %d,%d\n",(*llb)->val,(*lla)->val);
		int i=(*lla)->val-(*llb)->val;
		return i;
	}
	return 0;
}

int len=0;
list** sortlist(){
	len=listlen();
	list** l=(list**)malloc(sizeof(list*) * len);
	list* h=head;
	int i;
	for(i=0;h!=NULL;h=h->next,i++)l[i]=h;
	
	qsort(l,len,sizeof(list*),cmp);
	return l;
}

int main(){
	int cube[]={1,2,3};
	head=(list*)malloc(sizeof(list));
	head->next=NULL;
	
	showCube(cube);	
	
	printlist();
	printf("\ntotal:%d\n",cc);
	list** ll=sortlist();
	int i=0;
	for(;i<len;i++)
		printf("%d,",ll[i]->val);
}

